/*
 * dht11.c
 *
 *  Created on: Aug 18, 2021
 *      Author: LF
 */

#include"tim.h"
#include"gpio.h"
#include"main.h"

#define DHT11_In_init()   \
{     \
	GPIO_InitTypeDef GPIO_InitStruct = {0};  \
	GPIO_InitStruct.Pin = W1Dat_Pin;   \
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;    \
	GPIO_InitStruct.Pull = GPIO_PULLUP;     \
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;    \
	HAL_GPIO_Init(W1Dat_GPIO_Port, &GPIO_InitStruct);   \
}


#define DHT11_Out_init()   \
{   \
	GPIO_InitTypeDef GPIO_InitStruct = {0};  \
	GPIO_InitStruct.Pin = W1Dat_Pin;   \
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;    \
	GPIO_InitStruct.Pull = GPIO_NOPULL;     \
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;    \
	HAL_GPIO_Init(W1Dat_GPIO_Port, &GPIO_InitStruct);   \
}

#define DHT11_DQ_OUT(N) HAL_GPIO_WritePin(W1Dat_GPIO_Port,\
		W1Dat_Pin, N==1?GPIO_PIN_SET:GPIO_PIN_RESET)
#define DHT11_DQ_IN() HAL_GPIO_ReadPin(W1Dat_GPIO_Port, W1Dat_Pin)

/*主机发送起始信号*/
static void DHT11_StartSignal(void)
{
	DHT11_Out_init();

	/*主机拉低 >= 18ms*/
	DHT11_DQ_OUT(0);
	HAL_Delay(20);

	/*主机拉高 >=20-40us*/
	DHT11_DQ_OUT(1);
	delay_us(30);

	DHT11_In_init();

}

uint8_t DHT11_RespondSignal(void)
{
	uint8_t retry = 0;

	/*总线变为低电平说明从设备发送了响应信号：80us*/
	while(DHT11_DQ_IN() && retry <100)
	{
		retry++;
		delay_us(1);
	}

	/*超时没有收到响应信号*/
	if(retry >= 100)
		return 1;

	/*从设备再把总线拉高表示从设备要发送数据了:80us*/
	retry = 0;
	while(!DHT11_DQ_IN() && retry <100)
		{
			retry++;
			delay_us(1);
		}

	/*超时没有收到响应信号*/
	if(retry >= 100)
		return 1;


	return 0;
}

uint8_t DHT11_ReadBit(void)   //读取一个位
{
	uint8_t retry = 0;

	/*从设备回复的每个位数据以低电平标志开始：50us*/
	while(DHT11_DQ_IN() && retry <100)
	{
		retry++;
		delay_us(1);
	}

	/*数据位都用高电平表示，但高电平的长短决定了数据是1或0*/
	retry = 0;
	while(!DHT11_DQ_IN() && retry <100)
		{
			retry++;
			delay_us(1);
		}

	/*判断数据位是1(70us) or 0(26~28us)*/
	delay_us(40);
	if(DHT11_DQ_IN())
		return 1;
	else
		return 0;

}

uint8_t DHT11_ReadByte(void)  //读取一个字节返回位采集值
{
	uint8_t   i,dat;

	dat = 0;
	for(i=0; i<8; i++)
	{
		dat <<= 1;
		dat |= DHT11_ReadBit();  //每读取到一个位放到最后一位
	}

	return dat;
}

int DHT11_SampleData(float *temperature, float *humidity)
{
	uint8_t  humi_H8bit;
	uint8_t  humi_L8bit;
	uint8_t  temp_H8bit;
	uint8_t  temp_L8bit;
	uint8_t  check_sum;

	if(!temperature || !humidity)
		return -1;
	/*主机发起起始信号并等到从设备的响应信号*/
	DHT11_StartSignal();
	if(0 != DHT11_RespondSignal())
		return -2;

	humi_H8bit = DHT11_ReadByte();
	humi_L8bit = DHT11_ReadByte();
	temp_H8bit = DHT11_ReadByte();
	temp_L8bit = DHT11_ReadByte();
	check_sum = DHT11_ReadByte();

	if((humi_H8bit+humi_L8bit+temp_H8bit+temp_L8bit) != check_sum)
		return -3;

	*humidity = (humi_H8bit*100 + humi_L8bit) / 100.00;
	*temperature= (temp_H8bit*100 + temp_L8bit) / 100.00;

	return 0;

}
